/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.loja.view.component.aggregation;

import br.com.loja.model.service.Service;
import br.com.loja.model.service.exception.ServiceException;
import br.com.loja.model.service.factory.ServiceFactory;
import br.com.loja.view.component.factory.ViewHadler;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;

/**
 *
 * @author DavidLuiz
 */
public class EntityToMany<E> extends JList<E> implements ViewHadler<List<E>> {

    public EntityToMany(Class<E> clazz) throws ServiceException {
        setModel(buildListModel(clazz));
        setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    }

    public EntityToMany(List<E> database) throws ServiceException {
        setModel(buildListModel(database));
        setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    }

    private ListModel<E> buildListModel(Class<E> clazz) throws ServiceException {
        Service<E> service = getService(clazz);
        return getListModel(service);
    }

    private ListModel<E> buildListModel(List<E> database) throws ServiceException {
        Service<E> service = getService(database);
        return getListModel(service);
    }

    private ListModel<E> getListModel(Service<E> service) {
        DefaultListModel<E> listModel = new DefaultListModel<>();
        for (E element : service.list()) {
            listModel.addElement(element);
        }
        return listModel;
    }

    private Service<E> getService(Class<E> clazz) throws ServiceException {
        ServiceFactory serviceFactory = ServiceFactory.getServiceFactory();
        Service<E> service = serviceFactory.getService(clazz);
        return service;
    }

    private Service<E> getService(List<E> database) throws ServiceException {
        ServiceFactory serviceFactory = ServiceFactory.getServiceFactory(database);
        ParameterizedType parameterizedType = (ParameterizedType) database.getClass().getGenericSuperclass();
        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
        Class<E> type = (Class<E>) actualTypeArguments[0];
        Service<E> service = serviceFactory.getService(type);
        return service;
    }

    @Override
    public void setValueModel(List<E> value) {
        setSelectedIndices(getSelectedIndices(value));
        updateUI();

    }

    private int[] getSelectedIndices(List<E> value) {
        List<Integer> selectedList = new ArrayList<>();

        for (E elementSelected : value) {
            addSelectedIndex(elementSelected, selectedList);
        }

        int selectedCount = selectedList.size();
        int[] indices = new int[selectedCount];

        for (int i = 0; i < selectedCount; i++) {
            indices[i] = selectedList.get(i);
        }

        return indices;
    }

    private void addSelectedIndex(E elementSelected, List<Integer> selectedList) {
        for (int i = 0; i < getModel().getSize(); i++) {

            E currentElement = getModel().getElementAt(i);

            if (elementSelected.equals(currentElement)) {
                selectedList.add(i);
            }
        }
    }

    @Override
    public List<E> getValueModel() {
        return getSelectedValuesList();
    }

}
